#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/mman.h>
#include <unistd.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <math.h>
#include <signal.h>

// 全局变量用于优雅退出
volatile sig_atomic_t keep_running = 1;

// 信号处理函数
void handle_signal(int sig) {
    keep_running = 0;
}

int main(int argc, char const *argv[])
{
    // 注册信号处理
    signal(SIGINT, handle_signal);
    signal(SIGTERM, handle_signal);
    
    int fd_lcd = open("/dev/fb0", O_RDWR);
    if (fd_lcd < 0)
    {
        perror("open lcd error");
        return -1;
    }
    
    struct fb_var_screeninfo varfo;
    int retVal = ioctl(fd_lcd, FBIOGET_VSCREENINFO, &varfo);
    if (retVal < 0)
    {
        perror("get var error");
        close(fd_lcd);
        return -1;
    }

    // 检查像素格式
    if (varfo.bits_per_pixel != 32) {
        printf("Unsupported pixel format: %dbpp\n", varfo.bits_per_pixel);
        close(fd_lcd);
        return -1;
    }

    int Height = varfo.yres;
    int Width = varfo.xres;
    int fbb = varfo.bits_per_pixel / 8;
    long fb_size = Width * Height * fbb;

    // 初始化随机数生成器
    srand(time(NULL));
    
    // 定义颜色
    unsigned int Red = 0xFF3030;      // 红色
    unsigned int White = 0xF8F8FF;    // 白色
    unsigned int Blue = 0x0000FF;     // 蓝色边框

    unsigned int *map = mmap(NULL, 
                    fb_size, 
                    PROT_READ | PROT_WRITE, 
                    MAP_SHARED,
                    fd_lcd, 
                    0);
    if(map == MAP_FAILED)
    {
        perror("mmap error");
        close(fd_lcd);
        return -1;
    }    

    // 初始化圆形参数
    int radius = (Height < Width) ? Height/10 : Width/10; // 半径
    int border = radius / 10;        // 边框宽度
    
    // 随机初始位置和速度
    int center_x = rand() % (Width - 2*radius) + radius;
    int center_y = rand() % (Height - 2*radius) + radius;
    int vx = (rand() % 5) + 1; // x方向速度 (1-5像素/帧)
    int vy = (rand() % 5) + 1; // y方向速度 (1-5像素/帧)
    
    // 随机决定初始方向
    if (rand() % 2 == 0) vx = -vx;
    if (rand() % 2 == 0) vy = -vy;
    
    // 主动画循环
    while (keep_running) {
        // 1. 保存上一帧的圆形位置
        int prev_x = center_x;
        int prev_y = center_y;
        
        // 2. 更新圆形位置
        center_x += vx;
        center_y += vy;
        
        // 3. 边界碰撞检测
        if (center_x - radius < 0) {
            center_x = radius;
            vx = -vx;
        } else if (center_x + radius > Width) {
            center_x = Width - radius;
            vx = -vx;
        }
        
        if (center_y - radius < 0) {
            center_y = radius;
            vy = -vy;
        } else if (center_y + radius > Height) {
            center_y = Height - radius;
            vy = -vy;
        }
        
        // 4. 计算需要重绘的区域（最小化重绘）
        int min_x = (prev_x - radius - abs(vx) > center_x - radius) ? 
                    center_x - radius - abs(vx) : prev_x - radius - abs(vx);
        int max_x = (prev_x + radius + abs(vx) < center_x + radius + abs(vx)) ? 
                    center_x + radius + abs(vx) : prev_x + radius + abs(vx);
        int min_y = (prev_y - radius - abs(vy) > center_y - radius - abs(vy)) ? 
                    center_y - radius - abs(vy) : prev_y - radius - abs(vy);
        int max_y = (prev_y + radius + abs(vy) < center_y + radius + abs(vy)) ? 
                    center_y + radius + abs(vy) : prev_y + radius + abs(vy);
        
        // 确保区域在屏幕范围内
        min_x = (min_x < 0) ? 0 : min_x;
        max_x = (max_x > Width) ? Width : max_x;
        min_y = (min_y < 0) ? 0 : min_y;
        max_y = (max_y > Height) ? Height : max_y;
        
        // 5. 只重绘变化区域
        for (int y = min_y; y < max_y; y++)
        {
            for (int x = min_x; x < max_x; x++)
            {
                // 计算到当前圆心的距离
                int dx = x - center_x;
                int dy = y - center_y;
                int distance_sq = dx*dx + dy*dy;
                int radius_sq = radius * radius;
                
                // 计算到上一帧圆心的距离
                int prev_dx = x - prev_x;
                int prev_dy = y - prev_y;
                int prev_distance_sq = prev_dx*prev_dx + prev_dy*prev_dy;
                
                // 如果在当前圆内
                if (distance_sq <= radius_sq) {
                    // 绘制圆形（带边框）
                  
                        map[y * Width + x] = Red; // 红色填充
                    
                }
                // 如果在上一个圆内但不在当前圆内
                else if (prev_distance_sq <= radius_sq) {
                    // 恢复背景
                    map[y * Width + x] = White;
                }
                // 如果既不在当前圆也不在上一个圆
                else {
                    // 不需要重绘，跳过
                    continue;
                }
            }
        }
        
        // 6. 控制动画速度
        usleep(30000); // 30毫秒 (约33FPS)
    }
    
    // 退出前清除屏幕
    for (int y = 0; y < Height; y++)
    {
        for (int x = 0; x < Width; x++)
        {
            map[y * Width + x] = White;
        }
    }
    
    munmap(map, fb_size);
    close(fd_lcd);
    
    printf("程序已安全退出\n");

    return 0;
}


